home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-09-21 | 51.1 KB | 1,240 lines | [TEXT/MPS ] |
- Getting started: Setting up the DYNAMO cross-development system:
- <<< Version 4.2 >>>
-
-
- NOTE: Read the READ.ME file for Dynamo. The installation instructions
- will be found there.
-
-
-
- Now that we are installed, what did we install?
-
-
-
- First, information on BUILDAPP.SYSTEM:
-
-
- The BUILDAPP.SYSTEM program allows the developer to build a multiple-segment
- application into one program file, and to launch it simply on the //e.
- Segments are automatically relocated to appropriate banks of memory, and then
- the application is launched starting at any address in any bank chosen.
-
- BUILDAPP.SYSTEM uses a text file as a script for building the application.
- The default name for this text file is BUILDAPP.TEXT. This can be changed by
- modifying the pathname in the program BUILDAPP.SYSTEM. The pathname starts at
- the sixth byte of the file, memory location $2006 if BLOADed. The pathname is
- a pascal string. (This is the standard ProDOS way of giving the launched
- application a pathname.)
-
- To use the BUILDAPP.SYSTEM program, you will need a disk with ProDOS, the
- BUILDAPP.SYSTEM program, a build script file called BUILDAPP.TEXT, and all the
- segments of your application on one disk. This disk is now bootable. When
- the disk is booted, BUILDAPP.SYSTEM will construct a single executable block
- of code starting at address $2000. Then it may or may not prompt you as to
- whether or not you want to save this image. (The “whether or not” is
- configurable.) During development, you will often choose not to save it,
- since it takes just that much longer to get the application executing. Then
- you can test your latest addition or change to your application. To make a
- bootable disk without BUILDAPP.SYSTEM, you just save the application image to
- disk, and then copy the application to a disk with just ProDOS on it. If the
- application name ends with .SYSTEM, and it has a filetype of $FF, you have a
- bootable application.
-
-
- You may wish to develop on one machine, which writes the segments to the
- ProDOS disk, and then just boot the disk on another machine. This saves a lot
- of time booting into your development environment. There is also the
- advantage of always being able to look at the most current source while
- executing the program. You don't need two machines to develop, but it will
- definitely speed up the add/change/test development cycle every programmer
- goes through.
-
-
-
- How the application is built depends on the BUILDAPP.TEXT script file. Here
- is the explanation of this file:
-
- The first line of the build script is the pathname that will be placed at
- $2006 of the application. You may have no need for this, but if you are
- developing a system application, launchers may place a pathname there, and you
- may want a default.
-
- Lines 2-N are for the segments to be loaded. These lines have 2 or 3 fields,
- depending on the bit settings of first field.
-
-
- First field bit settings:
-
- Bits 0-3 are bank selection bits. The breakdown is as follows:
-
- Bit 0: Indicates ROM or language card. Off for ROM, on for language card.
- Bit 1: Indicates which language card (if bit 0 is on). Off for primary
- language card, on for auxiliary language card.
- Bit 2: Indicates 1st or 2nd $D000 bank of language card. Which language card
- is still indicated by bit 0 and 1. Off selects the secondary $D000
- bank ($C083), and on selects the primary $D000 bank ($C08B).
- Bit 3: Indicates primary or auxiliary 48k. Off for primary, on for auxiliary.
-
- Bit 4 is used to prevent a system-setup operation that is necessary for 8-bit
- applications that use the auxiliary stack. If it is necessary, then why use
- a bit to override it? The reason for this is that it is necessary only when
- an application is first started. Once it has been done, it does not have to
- be done again. It is possible to sub-launch a second application built with
- BUILDAPP.SYSTEM. This sub-launch should not reinitialize the secondary stack
- pointer value.
-
- Bit 5 must be off.
-
- Bit 6 indicates you wish this segment to be called immediately after it has
- been moved. This allows initialization segments to be called during the
- dispatch process. Initialization segments can not be in auxiliary 48K RAM.
- The initialization segment is jsr'ed to, so that after it has completed,
- the segment simply does an rts, and the dispatch process is continued.
- Here is an example use of an initial segment:
- You want to put 0's in the secondary $D000 bank of the auxiliary
- language card. You could do this by having a 4k block of 0's as a
- segment, and then have the dispatcher load that segment into the
- correct $D000 bank. This, of course adds 4k to the application
- size. An alternative would be to write an initial segment that
- would fill this $D000 bank with 0's. The initial segment address
- doesn't have to be in the $D000 address range, yet the bank is
- still selected. So, you could have some code than executes at
- $0800 that fills $D000-$DFFF with 0's. Once this is done, you
- would simply rts. After the job is done, the initial segment
- isn't needed any longer, and you could have a later segment
- load into the $0800 space.
-
- Bit 7 of field 1 being on indicates the end of the segment list. Bits 0-3
- still indicate which bank of memory, and the following field indicates the
- launch address within that bank. The correct bank is selected, and then a
- jmp instruction is executed to the designated address. The only restriction
- is that the starting location can not be in auxiliary 48k of RAM.
-
- Bits 8-14 must be off.
-
- Bit 15 indicates that you are going to use GSBUG in 8-bit mode. For GSBUG to
- work, it must be able to reserve 1024 bytes of consecutive memory in primary
- RAM. GS/OS reserves all of primary RAM (and more) for ProDOS. It does this
- by creating a handle that takes all of RAM from $0800 through $BFFF. It is
- BUILDAPP.SYSTEM that makes the 1024 bytes of RAM allocatable for GSBUG. It
- is not the application dispatcher itself. If you save the built application
- to disk, and then run the built application, no memory will be reserved for
- GSBUG. This is actually a feature. During the development process, when you
- are using BUILDAPP.SYSTEM, you can tell BUILDAPP.SYSTEM to reserve memory
- for GSBUG. When you are done using BUILDAPP.SYSTEM, and you do the final
- build of your application, your final application will not do anything special
- for GSBUG. Also, if you need to change which 1024 bytes of memory are used,
- you can do this simply by changing the build script for your application.
-
- The second field is the load address. This address is used differently,
- depending on the bit settings of field 1. If bits 7 and 15 are both off,
- then the value in this field indicates where the code or data should be
- moved to at application startup time. If bit 7 is on, then this address
- indicates the starting address of the application. If bit 15 is on, then
- this address indicates the start of 1024 bytes of primary 48k memory that
- GSBUG will use when invoked.
-
- The third field is the name of the segment itself. This can be a full or
- partial pathname. There is only a third field if bits 7 and 15 are both off.
-
- The next two lines indicate whether you want hex or decimal information
- indicating starting address and total application size.
-
- The next line indicates whether or not you want to be prompted to save the
- file, and if you don’t want to be prompted, what to do instead. To not be
- prompted, the first character of ths line needs to be a Y, N, or Q (or the
- lowercase equivalent). You will be prompted if the first character of this
- line is anything else. (Putting a ? here if you want to be prompted isn’t a
- bad idea. It acts as a placeholder, and is reasonably descriptive.)
-
- The final line indicates the application filetype, auxtype, and filename. The
- application builder will ask if you want the application saved. After the
- file is saved (or not), the application is launched for testing.
-
- NOTE: All numeric fields can be decimal or hex.
-
- The below is a sample build script that was used to make the application
- builder itself.
-
- There is only one segment for this application. The runtime was linked into
- the main code module, generating only one binary code segment.
-
- BUILDAPP.TEXT ;The default script filename.
- 0,$800,BUILD.BIN ;The buildapp application.
- $80,$800 ;Starting address.
- $ ;Display starting address in hex.
- $ ;Display application size in hex.
- N ;Don’t save file -- just launch it.
- $FF,0,BUILDAPP.SYSTEM ;Filetype, auxtype, and filename.
-
- The BUILDAPP.TEXT file can be up to 2045 bytes long.
-
- Bank switching will still have to occur within the application, as necessary.
- There is no getting around that on a //e. BUILDAPP.SYSTEM is to simplify the
- loading and starting of an application, by making it a single, launchable
- file.
-
-
-
- Below are the macros included in the runtime, and their basic usage:
-
- _____________________________________________________________
-
- OPERAND USAGE:
-
- If the operand represents an integer variable or string, then you do not put a
- # in front of it. Variables and strings are always either a ldx literal, or a
- ldy literal, so the # is assumed. When the macro is expanded, the # is put
- there automatically.
-
- If the operand represents a value, then you will need to put a # or an * in
- front of the operand. If you put a # in front of the operand, then it is a
- literal. If you put an * in front, then it uses the value at that address.
- This is similar to the C unary operator *.
-
- If the operand represents a 1-byte value, then you will need to put a < after
- the # or *. This tells the macros to load only the accumulator with a value
- (instead of the accumulator and y-register) and call the low-byte-only entry
- point instead.
-
- An extension has been added in version 3.1. You can now have as many levels
- of indirection as you want. A single * gives you a single level of indirection.
- (Value at, instead of value.) Two *’s in a row gives you two levels of
- indirection. This would be equivalent to a double-dereference in c.
-
- These macros are interfaces for the runtime routines associated with them.
- The runtime routines handle up to 128 integer variables, and up to 256
- strings. The runtime also has multi-dimension array support. The integer
- functions are simple add,sub,mul,div, and others. These others include mass-
- initialization, min, max, print decimal, etc. The string functions are most
- of what is available in AppleSoft, in various forms. The array functions are
- used to define a base pointer to a row of dta within the array, and then to
- index into and out of that row. There is also floating-point support, as well.
-
- The principle of the runtime routines is that the xreg holds a destination
- variable number (for ints: 0-254, for strings: 0-255). All runtimes preserve
- the xreg, therefore, you can do multiple operations to a single variable
- without having to reload the xreg. The values that are used on the xreg
- variable (the source data), is one of 3 forms for integers:
- 1. 1-byte value
- 2. 2-byte value
- 3. 2-byte integer variable.
- 1-byte values are placed in the acc. 2-byte values are placed in the acc,y
- (acc=lo, y=hi). 2-byte integer variables have the variable number placed in
- the yreg. (The yreg is not preserved by the runtime routines.) Once the
- source data is loaded (in acc, acc-y, or y), the proper call to the runtime
- routines is made. The 'proper' routine is based on the type of data the
- source is. (If the source is a variable, and we are adding, the macro will
- call the addvar routine.)
-
- The values that are used on the xreg variable (the source data), is one
- of 2 forms for floating-point:
- 1. 2-byte pointer to 5-byte AppleSoft floating-point value.
- 2. 5-byte floating-point variable.
- 2-byte pointers to floating-point values are placed in the acc,y
- (acc=lo, y=hi). 5-byte floating-point variables have the variable number
- placed in the yreg. (The yreg is not preserved by the runtime routines.)
- Once the source data is loaded (in acc-y, or y), the proper call to the
- runtime routines is made. The 'proper' routine is based on the type of data
- the source is. (If the source is a variable, and we are adding, the macro
- will call the faddvar routine.)
-
-
-
- Strings are also referenced by number. There are 3 tables for strings:
- 1. String length table.
- 2. Max string length table.
- 3. Pointer table.
- So, each string takes up four bytes, plus however long the max string length
- is. Having the pointer allows the program to point into memory that was never
- loaded or initialized. This can save time loading the application from disk.
- The string routines will never overwrite the buffer space allocated for them.
- The string will be truncated. So, you can append strings without worry about
- clobbering memory.
-
- Some code using the macros and runtime might look like:
-
- _restore textForBill ;Point at literal text.
- _readstr billStr ;Read text into string.
- _prstr ;Print the string.
- _hexpad #'0' ;Set hex padding to a 0.
- _rtcout #'$' ;Print a $.
- _varcpy bill,val ;Set bill to val.
- _addl ,#5 ;Add 5 to bill.
- (****** or: _add ,<#5 ******)
- _mulvar ,factor ;Multiply bill by factor.
- _vhexout ;Print bill in hex.
- rts
- textForBill dc.b 'Bill''s value in hex is: ',0
-
- We could replace the _restore, _readstr, _prstr, with:
- textForBill _write 'Bill''s value in hex is: ',0
-
- We could still read the text in the _write macro from elsewhere by:
- _restore textForBill+3 ;Point at literal text.
- _readstr billStr ;Read text into string.
-
- The +3 skips the jsr to the write routine (generated by _write). Both the
- _write and _readstr routines stop at a 0. (The _readstr ending character can
- be changed to whatever you want with the _readend macro, but the default stop
- character is a 0.)
-
-
- Below is a list of the macros, and how they are used:
-
-
- acorm
- xcorm
- ycorm
- axcorm
- aycorm
- fparm
- These macros are used by other macros for setting up parameters to the routines.
- For example: acorm stands for load A as a Constant OR from Memory.
-
-
- _skipbyte
- _skipword
- These macros are use to save bytes. Instead of jumping around a single byte or
- two bytes, skip byte generates a
- dc.b $24
- and _skipword generates a
- dc.b $2C
- These cause the next byte (or 2 bytes) to be skipped. _skipword must be used
- with some caution. Make sure that the address that is being Bit'ted isn't a
- soft-switch, or else you could do something nasty.
-
-
- _int
- An alternate form of aycorm. _int has more meaning to an application.
-
-
- _ptr
- An alternate alternate form of aycorm. Same reason as _int.
-
-
- _byte
- An alternate form of acorm.
-
-
- _rtreset
- This macro initializes everything necessary in the runtime. This allows a
- resume after the user presses a reset.
-
-
- _hibitchrs
- This macro is used to turn on the hi-bit for characters that are sent to
- rtcout.
-
-
- _lowbitchrs
- This macro is used to turn off the hi-bit for characters that are sent to
- rtcout.
-
-
- _regchrs
- This macro is used to make sure that characters sent to rtcout are used as-is.
- There will be no modification of the hi-bit.
-
-
- _rtcout op
- This macro prints a character. This character is either already in the acc
- (no operand), or what is described by the operand. The operand can either be
- an absolute or a value in memory.
-
-
- _write op1,op2,op3,...
- This macro prints a cstring. You can use as many operands as MPW allows. You
- can continue onto the next line with the line continuation character \. After
- all the operands are processed, the macro places a cstring 0 terminator
- character at the end of the string. This is done automatically. Placing one
- there yourself will define an extra one, which will end up being a BRK
- instruction in your code.
-
-
- _writecr
- This macro prints a carriage return.
-
-
- _space op
- This macro outputs op number of spaces. If there is no op, then
- the number of spaces to be output is assumed to be in the yreg.
-
-
- _repeat op
- This macro outputs op2 number of the character op1. If there is no op1,
- then the character is assumed to be in the acc. If there is no op2, then
- the number of times the char should be output is assumed to be in the yreg.
-
-
- _wrcstr op
- This macro prints a c string pointed to by the operand.
-
-
- _signed
- This macro sets signed mode. Printing decimal numbers is affected by this.
-
-
- _unsigned
- This macro sets unsigned mode. Printing decimal numbers is affected by this.
-
-
- _chngsgn
- This macro does a two's compliment on the variable. The result is also
- returned in acc,y.
-
-
- _decoutl op
- This macro prints a 1-byte decimal value. This value is either already in the
- acc (no operand), or what is described by the operand. The operand can either
- be an absolute or a value in memory.
-
-
- _vdecout op
- This macro prints a 2-byte decimal value. This value is stored in a variable.
- The variable number is either already in the xreg (no operand), or is
- determined by the operand.
-
-
- _decout op
- This macro prints a 1- or 2-byte decimal value. This value is either already
- in the acc,y (no operand), or what is described by the operand. The operand
- can either be an absolute or a value in memory. This macro optimizes. If the
- operand is an immediate value, and it is indicated to be a 1-byte value (by
- using <), then code is generated only to load the acc and decoutl is called
- instead of decout.
-
-
- _hexpad op
- This macro sets pad mode for hex. The value is either already in the acc (no
- operand), or what is described by the operand. The operand can either be an
- absolute or a value in memory. Printing hex numbers is affected by this.
-
-
- _hexnopad
- This macro sets no pad mode for hex. Printing hex numbers is affected by
- this.
-
-
- _hexoutl op
- This macro prints a 1-byte hex value. This value is either already in the acc
- (no operand), or what is described by the operand. The operand can either be
- an absolute or a value in memory. Since it is only printing a 1-byte value,
- the maximum amount of padding is one character.
-
-
- _vhexout op
- This macro prints a 2-byte hex value. This value is stored in a variable.
- The variable number is either already in the xreg (no operand), or is
- determined by the operand. The maximum amount of padding is three characters.
-
-
- _hexout op
- This macro prints a 2-byte hex value. This value is either already in the
- acc,y (no operand), or what is described by the operand. The operand can
- either be an absolute or a value in memory. The maximum amount of padding is
- three characters.
-
-
- _addvar op1,op2
- This macro adds a variable to the destination variable. If there is no op1,
- then the destination variable number is assumed to be in the xreg. If there
- is no op2, then the source variable number is assumed to be in the yreg. The
- value of the source variable is returned in acc,y.
-
-
- _addl op1,op2
- This macro adds a 1-byte value to the destination variable. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in the acc. The 1-byte value
- is returned in acc. The yreg is set to 0.
-
-
- _add op1,op2
- This macro adds a 2-byte value to the destination variable. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in acc,y. The 2-byte value
- is returned in acc,y. This macro optimizes. If op2 is an immediate value,
- and it is indicated to be a 1-byte value (by using <), then code is generated
- only to load the acc and addconl is called instead of addcon.
-
-
- _subvar op1,op2
- This macro subtracts a variable from the destination variable. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the source variable number is assumed to be in the yreg.
- The value of the source variable is returned in acc,y.
-
-
- _subl op1,op2
- This macro subtracts a 1-byte value from the destination variable. If there
- is no op1, then the destination variable number is assumed to be in the xreg.
- If there is no op2, then the value is assumed to be in the acc. The 1-byte
- value is returned in acc. The yreg is set to 0.
-
-
- _sub op1,op2
- This macro subtracts a 2-byte value from the destination variable. If there
- is no op1, then the destination variable number is assumed to be in the xreg.
- If there is no op2, then the value is assumed to be in acc,y. The 2-byte
- value is returned in acc,y. This macro optimizes. If op2 is an immediate
- value, and it is indicated to be a 1-byte value (by using <), then code is
- generated only to load the acc and subconl is called instead of subcon.
-
-
- _mulvar op1,op2
- This macro multiplies the destination variable by a variable. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the source variable number is assumed to be in the yreg.
- The result of the multiply is also returned in acc,y.
-
-
- _mull op1,op2
- This macro multiplies the destination variable by a 1-byte value. If there is
- no op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in the acc. The result of
- the multiply is also returned in acc,y.
-
-
- _mul op1,op2
- This macro multiplies the destination variable by a 2-byte value. If there is
- no op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in acc,y. The result of the
- multiply is also returned in acc,y. This macro optimizes. If op2 is an
- immediate value, and it is indicated to be a 1-byte value (by using <), then
- code is generated only to load the acc and _mulconl is called instead of
- mulcon.
-
-
- _divvar op1,op2
- This macro divides the destination variable by a variable. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the source variable number is assumed to be in the yreg.
- The remainder from the divide is returned in acc,y.
-
-
- _divl op1,op2
- This macro divides the destination variable by a 1-byte value. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in the acc. The remainder
- from the divide is returned in acc,y.
-
-
- _div op1,op2
- This macro divides the destination variable by a 2-byte value. If there is no
- op1, then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in acc,y. The remainder from
- the divide returned in acc,y. This macro optimizes. If op2 is an immediate
- value, and it is indicated to be a 1-byte value (by using <), then code is
- generated only to load the acc and _divconl is called instead of divcon.
-
-
- _var op
- This macro sets the current variable. The current variable is defined by a
- number in the xreg. All runtime functions preserve the xreg, so multiple
- operations can be done to the same variable without having to reload the xreg
- with the variable number.
-
-
- _vderef op
- This macro uses a variable as a pointer and sets that variable to the value to where
- that pointer currently points. The macro preserves all registers.
- The c equivalent would be (using longs instead if ints):
- long *ptrvar;
- ptrvar = (long *)*ptrvar;
-
-
- _set0 op
- This macro sets a variable to 0. If there is no op1, then the destination
- variable number is assumed to be in the xreg. The acc is set to 0.
-
-
- _varcpy op1,op2
- This macro sets a variable to another variable. If there is no op1, then the
- destination variable number is assumed to be in the xreg. If there is no op2,
- then the source variable number is assumed to be in the yreg.
-
-
- _setl op1,op2
- This macro sets a variable to a 1-byte value. If there is no op1, then the
- destination variable number is assumed to be in the xreg. If there is no op2,
- then the value is assumed to be in the acc.
-
-
- _set op1,op2
- This macro sets a variable to a 2-byte value. If there is no op1, then the
- destination variable number is assumed to be in the xreg. If there is no op2,
- then the value is assumed to be in acc,y. The 1-byte value is returned in
- acc. The yreg is set to 0. This macro optimizes. If op2 is an immediate
- value, and it is indicated to be a 1-byte value (by using <), then code is
- generated only to load the acc and _setconl is called instead of setcon.
-
-
-
- _setvars op1,op2,op3,op4,...
- This macro sets multiple variables to constant values. The macro is followed
- by as many operands as MPW allows. The line continuation character \ can be
- used. The odd operands are the variables to be set, and the even operands are
- the values they should be set to. Operand1 gets the value of operand 2, and
- so on. The macro automatically terminates the list with a 255 byte. This is
- why 255 is not allowed as a variable number.
-
-
- _minswap op1,op2
- This macro swaps the two variables if the xreg variable is bigger than the
- yreg variable. If there is no op1, then the destination variable number is
- assumed to be in the xreg. If there is no op2, then the source variable
- number is assumed to be in the yreg.
-
-
- _maxswap op1,op2
- This macro swaps the two variables if the xreg variable is smaller than the
- yreg variable. If there is no op1, then the destination variable number is
- assumed to be in the xreg. If there is no op2, then the source variable
- number is assumed to be in the yreg.
-
-
- _vsgncmp op1,op2
- This macro does a signed compare of two variables. The equal status is true
- if the variables are equal. If the xreg variable is greater or equal, then
- the carry is set. If the xreg variable is smaller, then the carry is clear.
- If there is no op1, then the variable number is assumed to be in the xreg. If
- there is no op2, then the variable number is assumed to be in the yreg. Once
- op1 and op2 are loaded into the registers, if necessary, the registers are
- preserved.
-
-
- _vcmp op1,op2
- This macro does an unsigned compare of two variables. The equal status is
- true if the variables are equal. If the xreg variable is greater or equal,
- then the carry is set. If the xreg variable is smaller, then the carry is
- clear. If there is no op1, then the variable number is assumed to be in the
- xreg. If there is no op2, then the variable number is assumed to be in the
- yreg. Once op1 and op2 are loaded into the registers, if necessary, the
- registers are preserved.
-
-
- _sgncmp op1,op2
- This macro works the same as _vsgncmp, except that it compares a variable to a
- constant. Once op1 and op2 are loaded into the registers, if necessary, the
- registers are preserved.
-
-
- _cmp op1,op2
- This macro works the same as _vcmp, except that it compares a variable to a
- constant. All Once op1 and op2 are loaded into the registers, if necessary,
- the registers are preserved.
-
-
- _rndseed op
- This macro is used to seed the random number generator. If there is no op1,
- then the random seed is assumed to be in the acc,y.
-
-
- _random op
- This macro is used to return a random number from 0 to op - 1. If there is no
- op1, then the random number limit is assumed to be in the acc,y.
-
-
- _strval op
- This macro takes the value of a string and returns it in the acc,y. If there
- is no op1, then the string number is assumed to be in the xreg.
-
-
- _midstrval op1,op2
- This macro takes the value of op1 string starting at op2 character and returns
- it in the acc,y. If there is no op1, then the string number is assumed to be
- in the xreg. If there is no op2, then the character number is assumed to be
- in the yreg.
-
-
- _prstr op
- This macro prints the entire string. If there is no op1, then the string
- number is assumed to be in the xreg.
-
-
- ***************************************
-
-
- _out2str op
- This macro redirects output to the string. If there is no op1, then
- the string number is assumed to be in the xreg.
-
-
- _nullstr op
- This macro clears the string. If there is no op1, then
- the string number is assumed to be in the xreg.
-
-
- _out2stroff
- This macro resets output to the setting prior to calling out2str.
- out2str can be called multiple times, and only one call to out2stroff
- is needed. (out2str saved the output hook if it is DIFFERENT than
- what out2str sets it to.)
-
-
- _prleftstr op1,op2
- This macro prints op1 string starting at the first character for op2
- characters. If there is no op1, then the string number is assumed to be in
- the xreg. If there is no op2, then the number of characters is assumed to be
- in the acc.
-
-
- _prmidstr op1,op2,op3
- This macro prints op1 string starting at the op2 character for op3 characters.
- If there is no op1, then the string number is assumed to be in the xreg. If
- there is no op2, then the character number is assumed to be in the yreg. If
- there is no op3, then the number of characters is assumed to be in the acc.
-
-
- _leftstrcpy op1,op2,op3
- This macro copies op3 characters from op2 string to op1 string. If there is
- no op1, then the destination string number is assumed to be in the xreg. If
- there is no op2, then the source string number is assumed to be in the yreg.
- If there is no op3, then the number of characters is assumed to be in the acc.
-
-
- _strcpy op1,op2
- This macro copies op2 string to op1 string. If there is no op1, then the
- destination string number is assumed to be in the xreg. If there is no op2,
- then the source string number is assumed to be in the yreg.
-
-
- _midstrcpy op1,op2,op3,op4
- This macro copies op4 characters, starting at op3 character from op2 string to
- op1 string. If there is no op1, then the destination string number is assumed
- to be in the xreg. If there is no op2, then the source string number is
- assumed to be in the yreg. If there is no op3, then the character number is
- assumed to be in the acc. If there is no op4, then all characters to the end
- of the source string will be copied to the destination string. The op4 case
- is the only case where the assumed value is a particular value (#255), instead
- of what is in a register. This is the case because there are only three
- registers.
-
-
- _leftstrcat op1,op2,op3
- This macro concatenates op3 characters of op2 string onto op1 string. If
- there is no op1, then the destination string number is assumed to be in the
- xreg. If there is no op2, then the source string number is assumed to be in
- the yreg. If there is no op3, then the number of characters is assumed to be
- in the acc.
-
-
- _strcat op1,op2
- This macro concatenates op2 string onto op1 string. If there is no op1, then
- the destination string number is assumed to be in the xreg. If there is no
- op2, then the source string number is assumed to be in the yreg.
-
-
- _midstrcat op1,op2,op3,op4
- This macro concatenates op4 characters starting at op3 character from op2
- string onto op1 string. If there is no op1, then the destination string
- number is assumed to be in the xreg. If there is no op2, then the source
- string number is assumed to be in the yreg. If there is no op3, then the
- character number is assumed to be in the acc. If there is no op4, then all
- characters to the end of the source string will be concatenated to the
- destination string. The op4 case is the only case where the assumed value is
- a particular value (#255), instead of what is in a register. This is the case
- because there are only three registers.
-
-
- _litstr op1,op2,op3,...
- This macro works very much like _write, except that the characters are not
- printed. They are copied into the designated string. If there is no
- designated string, then it is assumed that the xreg already holds the string
- number.
-
-
- _strchr op1,op2
- This macro returns the op2th character of op1 string. If there is no op1,
- then the destination string number is assumed to be in the xreg. If there is
- no op2, then the character number is assumed to be in the acc.
-
-
- _strloc op1
- This macro returns the physical location of op1 string in memory. The string
- location is returned in acc,y.If there is no op1, then the destination string
- number is assumed to be in the xreg.
-
-
- _cstr op1,op2,op3,...
- This macro is used to generate a cstring using the same syntax as other
- macros. It works very much like _write and _litstr in the way it handles
- parameters. The only thing that this macro does, however, is define data.
-
-
- _restore op
- This macro sets the read data pointer. If there is no op, then the address
- for reading data is assumed to be in the acc,y.
-
-
- _readint op
- This macro reads an int from the current data pointer and advances the pointer
- by two bytes. If there is no op1, then the destination variable number is
- assumed to be in the xreg.
-
-
- _readstr op
- This macro reads string data into the designated string until the end-of-
- string character is encountered. The data pointer is then set to point after
- this end-of-string character. If there is no op1, then the destination string
- number is assumed to be in the xreg.
-
-
- _readend op
- This macro is used to set the end-of-string character for _readstr. If there
- is no op1, then the _readstr ending character is assumed to be in the acc.
-
-
- The array handling is simple pointer-based storage and retrieval. There is
- also some logic for multiple-dimensioned arrays. This system can handle
- arrays up to four dimensions deep. With a little work, this can be expanded
- to any number. The system allows for easy expansion to more dimensions. It
- works by having the application first give a description of the array. This
- description consists of the location of the array, the size of the elements in
- the array (byte or word), and what size the dimensions are. There are
- actually four pointers into the array area. The first one is always the base
- address. When the base address is first established, all four pointers are
- set to the base address. If you then wish to index into the array, you tell
- the runtime at what point in the array you wish to access for each level of
- subscript. If a subscript is omitted at the beginning of the index list, then
- it is assumed that the pointer for that level is already what you want. If a
- subscript is omitted after the first subscript, then that subscript is assumed
- to be 0.
-
- For example:
- We have a four dimensional array of words, called things, equated to
- address $4000. We would declare the array with the _array macro as
- follows:
- _array #things,#2,#3,#4,#5,#6
-
- This line means "use the memory at #things as an array of elements that are
- 2 bytes each. (The array access routines will use the element size from the
- last _array macro.) The array is is 3 by 4 by 5 by 6 in size." The array
- handling routines now use this information when getting and putting data to
- the array. The routines only keep track of one array. If you wish to
- switch between two or more arrays, you will have to reissue _array commands.
- The _array command does not allocate or protect any memory. It just gets
- the relevant information for the array. Thus, you can switch arrays as
- often as you want. Of course, there is some time overhead in switching, but
- it is rather minimal.
-
- If we wished to get the element things(1,3,4,5), and place it in the
- variable thing, we would do the following:
- _index #1,#3,#4
- _get thing,#5
-
- The _index macro builds pointers for the array into each level of
- subscript. The _get macro indexes (using #5) from the lowest level
- pointer, and gets that word and stores it in the variable thing. If we
- then wish to get the element things(1,3,4,4), we would:
- _get thing,#4
-
- We don't have to recalculate any pointers. They are still intact from
- the above _index macro. If we wish to change any of the subscripts,
- other than the last one, we will have to issue another _index macro.
- Lets say that we want the element things(1,2,0,5). Knowing that the
- previous _index macro got the element things(1,3,4,5), we can minimize
- the pointer math by having the _index macro redo only the data that is
- no longer valid. We would do an _index macro as follows:
- _index ,#2
- _get thing,#5
-
- The first subscript is the same. Therefore, the pointer for the first
- subscript is correct. The pointer for the second subscript is generated
- from the first (just as the pointer for the first is generated from the
- base address of the array). So, we don't have to mention the first
- subscript again. Not doing so saves code. Once any subscript pointer
- is recalculated, all the lower level pointers are set to that value.
- This means that there is an assumption that all the remaining subscripts
- are zero. If this is indeed the case, they don't have to be mentioned
- either. In this example, the third subscript is zero. So, it doesn't
- have to be mentioned either. This method of separate pointers for
- different levels of the array can be very efficient. It also can be
- confusing. If it is not clear whether you can leave subscripts out,
- don't. It will still work with all of the subscripts, although it will
- be more code than necessary.
-
- There is another form of the _index macro. It is the _vindex macro.
- This is used when the index value is stored in a variable. One
- unfortunate syntax limitation is that you can't mix the two types on one
- line. You still can mix the two types, however, when indexing into an
- array. For example:
- bob = things(color, 3, type, 5)
-
- would be done like:
- _vindex color
- _index ,#3
- _vindex ,,type
- _get bob,#5
-
-
- The following macros are used to define and access arrays.
-
- _array loc,elesize,op1,op2,op3,op4
- This macro prepares the array handling routines to work on the defined array.
- The operand loc is either the address of the array (when preceded by a #
- sign), or a 2-byte location where the address to the array is stored (when
- preceded by an *). The operand elesize determines the size of the elements in
- the array. The elements can be any size, although the element access routines
- will only handle 1, 2, and 5 byte sizes for elements. Operands op1 through op4
- describe the dimensions of the array. These must be constants. Operands op2
- through op4 are optional. The array may only be linear, in which case, op2
- through op4 would have no function. The operand op1 is actually not used. It
- is just for commenting purposes. The array routines do not do any range
- checking, and all that op1 is good for is to determine if the first subscript
- is out of range. You must have an op1, however, as a placeholder. This is to
- encourage it being used, as it is useful when reading the source code.
-
-
- _index op1,op2,op3
- This macro is used to calculate a pointer into the array. There are actually
- four pointers. The first three are used as partial results from previous
- calculations, so that all subscripts don't have to be involved every time
- there is a calculation to determine the specific element of the array. When
- the pointer for op1 is calculated, the resulting offset is added to the base
- array pointer (defined with the _array macro). This is then stored as the
- 2nd, 3rd, and 4th level pointers. If there are no more operands, then the
- effective pointer into the array will be this value. If op2 and op3 were
- zero, then this value would be correct. The assumption in this case is that
- any undeclared subscripts beyond the first one declared are zero. So, if your
- array is only two-dimensional, you would then never declare an op2 or op3, and
- they would therefore never affect the pointer into the array. An interesting
- aside to this is that one array can actually be considered to have a variable
- number of dimensions. Let's say that you have an array that is 10x10x10.
- This array could also be viewed as a 10x100 array. Both have the same number
- of elements. Using the _index macro differently, you could access the array
- either way. For example:
- _index #5
- _get value,#55
- would work as well as
- _index #5,#5
- _get value,#5
- This flexibility can be very useful. (It can also be confusing.) If you have
- a case where you know that the first subscript is the same as the last time
- you used the _index (or _vindex) macro, you can choose not to restate that
- subscript. You might even have a situation where the second subscript is the
- same also. In these cases, you can choose to leave those operand fields
- empty. This will produce less code than if you mentioned them. (There is an
- overhead of 7 bytes per index with the _index macro, and an overhead of 5
- bytes with the _vindex macro.)
- The syntax for this would look like: _index ,,#5
- The commas are necessary to indicate that subscripts 1 and 2 are already
- defined, and that you are referring to subscript 3. If the commas were not
- there, the _index macro would assume that the #5 is the first subscript, and
- that subscripts 2 and 3 are zero, or not used at all. This macro optimizes.
- If an operand is an immediate value, and it is indicated to be a 1-byte value
- (by using <), then code is generated only to load the acc and arraylindxN is
- called instead of arrayindxN.
-
-
- _vindex op1,op2,op3
- This macro works just like _index, except that the operands are variables,
- instead of constants or values at a particular memory location. This is
- useful when you want to use variable subscripts.
-
-
- _get op1,op2
- This macro is used to get an element from the array. The operand op2 is
- the right-most subscript in the array. This value can be either a constant,
- or a value in memory. The operand op1 is the variable to store the array
- value into. If the element size is byte, then the hi-byte of the integer
- variable will be set to 0. If the element size is word, then the word is
- copied into the integer variable. If the element size is float, then the
- 5-byte element is copied into the variable.
-
-
- _getl op1,op2
- This macro is used to get an element from the array using a 1-byte index.
- The operand op2 is the right-most subscript in the array. This value can be
- either a constant, or a value in memory. The operand op1 is the variable to
- store the array value into. (See _get.)
-
-
- _put op1,op2
- This macro is used to put an element into the array. The operand op2 is
- the right-most subscript in the array. This value can be either a constant,
- or a value in memory. The operand op1 is the variable that holds the value
- to be stored into the array.
-
-
- _getl op1,op2
- This macro is used to put an element into the array using a 1-byte index.
- The operand op2 is the right-most subscript in the array. This value can be
- either a constant, or a value in memory. The operand op1 is the variable
- that holds the value that will be placed in the array. (See _put.)
-
-
- _vget op1,op2
- This macro works just like _get, except that the operand op2 is a variable.
-
-
- _vput op1,op2
- This macro works just like _put, except that the operand op2 is a variable.
-
-
- _getnext op
- This macro gets the next element from the current array.
-
-
- _putnext op
- This macro puts the next element into the current array.
-
-
-
- ***************************************
- ***************************************
- ***************************************
-
-
- _fstrval op
- This macro takes the value of a string and returns it in the acc,y.
- If there is no op1, then the string number is assumed to be in the xreg.
-
-
- _fmidstrval op1,op2
- This macro takes the value of op1 string starting at op2 character and
- returns it in the acc,y. If there is no op1, then the string number is
- assumed to be in the xreg. If there is no op2, then the character number
- is assumed to be in the yreg.
-
-
- _readfloat op
- This macro reads a float from the current data pointer and advances the
- pointer by five bytes. If there is no op1, then the destination variable
- number is assumed to be in the xreg.
-
-
- _i2f op
- This macro converts an integer variable into a floating-point variable.
-
-
- _f2i op
- This macro converts a floating-point variable into an integer variable.
-
-
- _fout op
- This macro prints a float value. fout expects a pointer to the float.
- The pointer is either already in a,y (no operand), or is
- determined by the operand.
-
-
- _fvout op
- This macro prints a float value. This value is stored in a variable.
- The variable number is either already in the xreg (no operand), or is
- determined by the operand.
-
-
- _fmulvar op1,op2
- This macro multiplies the destination float variable by a float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg.
-
-
- _fmul op1,op2
- This macro multiplies the destination float variable by a float constant.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
-
-
- _fdivvar op1,op2
- This macro divides the destination float variable by a float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg.
-
-
- _fdiv op1,op2
- This macro divides the destination float variable by a float constant.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
-
-
- _faddvar op1,op2
- This macro adds a float variable to the destination float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg.
-
-
- This macro adds a float constant the destination float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
- _fadd op1,op2
-
-
- _fsubvar op1,op2
- This macro subtracts a float variable from the destination float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg.
-
-
- _fsub op1,op2
- This macro subtracts a float constant from the destination float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
-
-
- _fv2v op1,op2
- This macro raises the destination float variable by the source float variable.
- If there is no op1, then the destination variable number is assumed to be in
- the xreg. If there is no op2, then the source variable number is assumed to
- be in the yreg.
-
-
- _fv2con op1,op2
- This macro raises the destination float variable by the a float constant.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
-
-
- _fsgn op
- This macro gets the sign of the destination float variable and stores it in
- the destination variable. If there is no op, then the destination variable
- number is assumed to be in the xreg.
-
-
- _fabs op
- This macro gets the absolute value of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _fint op
- This macro gets the integer value of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _fsqr op
- This macro gets the square root of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _flog op
- This macro gets the log base e of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _fexp op
- This macro raises e to the destination float variable power and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _frnd op
- This macro forms a 'random' number and stores it in the destination
- variable. If there is no op, then the destination variable number
- is assumed to be in the xreg.
-
-
- _fcos op
- This macro gets the cos of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _fsin op
- This macro gets the sin of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _ftan op
- This macro gets the tan of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _fatn op
- This macro gets the arctan of the destination float variable and
- stores it in the destination variable. If there is no op, then the
- destination variable number is assumed to be in the xreg.
-
-
- _i2fsetl op1,op2
- This macro sets a float variable to a 1-byte value. If there is no op1,
- then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in the acc.
-
-
- _i2fset op1,op2
- This macro sets a float variable to a 2-byte value. If there is no op1,
- then the destination variable number is assumed to be in the xreg. If
- there is no op2, then the value is assumed to be in the acc.
-
-
- _i2fsetvars
- This macro is used to set a bunch of float variables to integer constant
- values. There must be a non-zero even number of parameters. The odd
- parameters are the variables, and the even parameters are the constant
- values for the preceeding parameter. The setvars routine uses the
- return address as a pointer to the data (just like the write routine).
- It simply sets the designated variable to the designated constant until
- it encounters a 255 as a variable value. A 255 is reserved for this
- purpose. This macro places a 255 at the end of the data list
- automatically.
-
-
- _fsetvars
- This macro is used to set a bunch of float variables to float constant
- values. There must be a non-zero even number of parameters. The odd
- parameters are the variables, and the even parameters are the constant
- values for the preceeding parameter. The setvars routine uses the
- return address as a pointer to the data (just like the write routine).
- It simply sets the designated variable to the designated constant until
- it encounters a 255 as a variable value. A 255 is reserved for this
- purpose. This macro places a 255 at the end of the data list
- automatically.
-
-
- _fset op1,op2
- This macro sets the destination float variable to a float constant.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source float pointer is
- assumed to be in a,y.
-
-
- _fset0 op
- This macro sets the destination float variable to 0.
-
-
- _fvcmp op1,op2
- This macro compares the destination float variable with a float variable.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg. The equal status is true if the variables are
- equal. If the xreg variable is greater or equal, then the carry is set.
- If the xreg variable is smaller, then the carry is clear.
-
-
- _fcmp op1,op2
- This macro compares the destination float variable with a float constant.
- If there is no op1, then the destination variable number is assumed to be
- in the xreg. If there is no op2, then the source variable number is
- assumed to be in the yreg. The equal status is true if the values are
- equal. If the xreg variable is greater or equal, then the carry is set.
- If the xreg variable is smaller, then the carry is clear.
-
-
- _fvarcpy op1,op2
- This macro sets a float variable to another float variable. If there is
- no op1, then the destination variable number is assumed to be in the
- xreg. If there is no op2, then the source variable number is assumed
- to be in the yreg.
-
-
- _asc2fp op
- This macro generates an AppleSoft floating-point number.
- It is generated in-line, with a dc.b statement.
-
-